package com.ubxtech.wecom.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.ubxtech.core.dto.MsgSendAddUpdateWecomDTO;
import com.ubxtech.core.dto.MsgSendDTO;
import com.ubxtech.core.dto.MsgSendWecomDTO;
import com.ubxtech.core.exception.RRException;
import com.ubxtech.wecom.properties.WecomProperties;
import com.ubxtech.wecom.service.WecomTokenService;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * @author Victor.Xiao
 * @since 2023-12-15 11:05
 **/
@Slf4j
public class WecomMsgUtil {
    private static WecomProperties wecomProperties;
    private static WecomTokenService wecomTokenService;
    private WecomMsgUtil() {}

    /** 请求超时时间 */
    public static int TIMEOUT_MILL = 10000;

    public static WecomMsgUtil getInstance() {
        return WecomMsgUtil.WecomMsgHolder.INSTANCE;
    }

    public static WecomProperties getWecomProperties() {
        return wecomProperties;
    }

    public void setWecomProperties(WecomProperties wecomProperties) {
        WecomMsgUtil.wecomProperties = wecomProperties;
    }

    public void setWecomTokenService(WecomTokenService wecomTokenService) {
        WecomMsgUtil.wecomTokenService = wecomTokenService;
    }


    /**
     * 发送企业消息到个人
     * @author Victor.Xiao
     * @since 2023-07-26 17:53
     * @param userIds 成员id
     * @param content 消息内容
     */
    public static void sendMessage(List<String> userIds , String content) {
        if (StrUtil.isBlank(content) || CollectionUtil.isEmpty(userIds)) {
            log.error("发送企业微信到用户内容为空,{},{}", userIds, content);
            return;
        }

        Map<String, Object> robotRequest = new HashMap<>();
        robotRequest.put("msgtype", "text");
        robotRequest.put("touser", StrUtil.join("|",userIds));
        robotRequest.put("toparty", "");
        robotRequest.put("totag", "");
        robotRequest.put("agentid", wecomProperties.getAgentId());
        Map<String, Object> requestContent = new HashMap<>();
        requestContent.put("content", content);
        robotRequest.put("text",requestContent);
        String body = HttpUtil.post(wecomProperties.getMessageSendUserUrl()+ "?access_token=" + getToken(),JSONObject.toJSONString(robotRequest),TIMEOUT_MILL);
        log.info("发送企业消息到个人结果:{}", body);
        checkWecomResp(JSONObject.parseObject(body));
    }


    /**
     * 发送企业应用消息到群聊
     * @author Victor.Xiao
     * @since 2023-07-26 17:53
     * @param chatids 企业微信群聊id
     * @param content 消息内容
     * @param usernameList 拼接艾特的人名
     */
    public static void sendAppMessage( List<String> chatids , String content,List<String> usernameList) {
        if (StrUtil.isBlank(content) || CollectionUtil.isEmpty(chatids)) {
            log.error("发送企业微信到群聊内容为空,{},{}", chatids, content);
            return;
        }
        if (CollectionUtil.isNotEmpty(usernameList)) {
            StringBuilder sb = new StringBuilder();
            sb.append(content);
            for (String username : usernameList) {
                sb.append(",@").append(username);
            }
            content = sb.toString();
        }
        for (String chatId : chatids) {
            Map<String, Object> robotRequest = new HashMap<>();
            robotRequest.put("msgtype", "text");
            robotRequest.put("chatid", chatId);
            Map<String, Object> requestContent = new HashMap<>();
            requestContent.put("content", content);
            robotRequest.put("text",requestContent);
            String body = HttpUtil.post(wecomProperties.getAppChatSendUrl()+ "?access_token=" + getToken(),JSONObject.toJSONString(robotRequest),TIMEOUT_MILL);
            log.info("发送企业应用消息到群聊结果:{}", body);
            checkWecomResp(JSONObject.parseObject(body));

        }
    }


    /**
     * 发送机器人消息到群聊
     * @author Victor.Xiao
     * @since 2023-07-26 17:53
     * @param webhookUrl 机器人发消息地址
     * @param content 消息内容
     * @param userids 要艾特的人
     */
    public static void sendRobotMessage( String webhookUrl , String content,List<String> userids) {
        if (StrUtil.isBlank(content) || StrUtil.isBlank(webhookUrl) ) {
            log.error("发送企业微信到群聊内容为空,{},{}", webhookUrl, content);
            return;
        }
        Map<String, Object> robotRequest = new HashMap<>();
        robotRequest.put("msgtype", "text");
        Map<String, Object> requestContent = new HashMap<>();
        requestContent.put("content", content);
        if (CollectionUtil.isNotEmpty(userids)) {
            requestContent.put("mentioned_list", userids);
        }
        robotRequest.put("text",requestContent);

        String body = HttpUtil.post(webhookUrl,JSONObject.toJSONString(robotRequest),TIMEOUT_MILL);
        log.info("发送机器人消息到群聊结果:{}", body);
        checkWecomResp(JSONObject.parseObject(body));
    }


    /**
     * 创建app群聊
     * @author Victor.Xiao
     * @since 2023-07-27 15:14
     * @param chatid 群聊的唯一标志，不能与已有的群重复；字符串类型，最长32个字符。只允许字符0-9及字母a-zA-Z。如果不填，系统会随机生成群id
     * @param name 群聊名，最多50个utf8字符，超过将截断
     * @param owner 指定群主的id。如果不指定，系统会随机从userlist中选一人作为群主
     * @param userIds 群成员id列表。至少2人，至多2000人
     * @return java.lang.String 返回群聊id
     */
    public static String createAppChat(String chatid,String name , String owner,List<String> userIds) {
        if (StrUtil.isBlank(name) || CollectionUtil.isEmpty(userIds)) {
            log.error("创建企业微信群内容为空,{},{},{}", name, owner,userIds);
            throw new RRException("创建企业微信群参数有误");
        }

        if (StrUtil.isBlank(owner)) {
            owner = userIds.get(0);
        }

        Map<String, Object> robotRequest = new HashMap<>();
        robotRequest.put("name", name);
        robotRequest.put("owner", owner);
        robotRequest.put("userlist",userIds);
        if (StrUtil.isNotBlank(chatid)) {
            robotRequest.put("chatid",chatid);
        }
        String body = HttpUtil.post(wecomProperties.getAppChatCreateUrl()+ "?access_token=" + getToken(),JSONObject.toJSONString(robotRequest),TIMEOUT_MILL);
        log.info("创建企业微信群消息结果:{}", body);
        JSONObject respJson = JSONObject.parseObject(body);
        checkWecomResp(respJson);
        chatid = respJson.getString("chatid");
        if (StrUtil.isBlank(chatid)) {
            throw new RRException("创建企业微信群失败");
        }
        return chatid;
    }



    /**
     * 修改app群聊
     * @author Victor.Xiao
     * @since 2023-07-27 16:10
     * @param chatid 群聊id
     * @param name 新的群聊名。若不需更新，请忽略此参数。最多50个utf8字符，超过将截断
     * @param owner 新群主的id。若不需更新，请忽略此参数。课程群聊群主必须在设置的群主列表内
     * @param addUserList 添加成员的id列表
     * @param delUserList 踢出成员的id列表
     */
    private static void updateAppChat(String chatid, String name, String owner, List<String> addUserList,List<String> delUserList) {
        if (StrUtil.isBlank(chatid) || StrUtil.isBlank(name)) {
            log.error("修改企业微信群内容为空,{},{},{}",chatid, name, owner);
            return ;
        }
        if (CollectionUtil.isEmpty(addUserList) && CollectionUtil.isEmpty(delUserList)) {
            log.error("修改企业微信群成员为空,{},{}",addUserList, delUserList);
            return ;
        }

        Map<String, Object> robotRequest = new HashMap<>();
        robotRequest.put("name", name);
        robotRequest.put("chatid", chatid);
        if (StrUtil.isNotBlank(owner)) {
            robotRequest.put("owner", owner);
        }
        if (!CollectionUtil.isEmpty(addUserList)) {
            robotRequest.put("add_user_list", addUserList);
        }
        if (!CollectionUtil.isEmpty(delUserList)) {
            robotRequest.put("del_user_list", delUserList);
        }
        String body = HttpUtil.post(wecomProperties.getAppChatUpdateUrl()+ "?access_token=" + getToken(),JSONObject.toJSONString(robotRequest),TIMEOUT_MILL);
        log.info("修改企业微信群消息结果:{}", body);
        JSONObject respJson = JSONObject.parseObject(body);
        checkWecomResp(respJson);
    }


    /**
     * 获取企业微信接口token
     * @author Victor.Xiao
     * @since 2023-07-26 18:01
     * @return java.lang.String
     */
    public static String getToken() {
        return wecomTokenService.getToken(wecomProperties.getCorpId(), wecomProperties.getCorpSecret(), wecomProperties.getTokenUrl());
    }

    /**
     * 校验企业微信接口是否有误
     * @author Victor.Xiao
     * @since 2023-07-28 10:30
     * @param jsonObject jsonObject
     */
    public static void checkWecomResp(JSONObject jsonObject ) {
        if (jsonObject == null || jsonObject.getInteger("errcode") == null ) {
            log.error("请求企业微信api有误,{}",jsonObject);
            throw new RRException("请求企业微信api有误");
        }
        if (jsonObject.getInteger("errcode") != 0) {
            log.error("请求企业微信api有误,{}",jsonObject);
            if (jsonObject.getInteger("errcode") == 60020) {
                throw new RRException("not allow to access from your ip");
            }
            throw new RRException("请求企业微信api有误");
        }
    }


    /**
     * 发送消息
     * @author Victor.Xiao
     * @since 2023-07-28 10:29
     * @param msgSendWecomDTO msgSendWecomDTO
     */
    public static void send(MsgSendWecomDTO msgSendWecomDTO) {

        log.debug("发送企业微信信息:{}",msgSendWecomDTO);
        if (StrUtil.isBlank(msgSendWecomDTO.getChatid()) && CollectionUtil.isEmpty(msgSendWecomDTO.getUserids())) {
            log.error("发送消息参数为空:{}", msgSendWecomDTO);
            return;
        }
        if (StrUtil.isNotBlank(msgSendWecomDTO.getChatid())) {
            //机器人
            if (msgSendWecomDTO.getChatid().startsWith("http")|| msgSendWecomDTO.getChatid().startsWith("HTTP")) {
                WecomMsgUtil.sendRobotMessage(msgSendWecomDTO.getChatid(), msgSendWecomDTO.getContent(), msgSendWecomDTO.getUserids());
            }
            //群聊
            else {
                WecomMsgUtil.sendAppMessage(Arrays.asList(msgSendWecomDTO.getChatid()), msgSendWecomDTO.getContent(),msgSendWecomDTO.getUsernameList());
            }
        }
        //直接发送到人
        else if (CollectionUtil.isNotEmpty(msgSendWecomDTO.getUserids())) {
            WecomMsgUtil.sendMessage(msgSendWecomDTO.getUserids(), msgSendWecomDTO.getContent());
        }


    }


    /**
     * 发送消息
     * @author Victor.Xiao
     * @since 2023-07-28 10:29
     * @param msgDTO msgDTO
     */
    public static <T> void send(MsgSendDTO<T> msgDTO) {

        log.debug("发送企业微信信息:{}",msgDTO);
        Object object = msgDTO.getContent();
        //创建群聊
        if ("createAppChat".equalsIgnoreCase(msgDTO.getTopic())) {
            MsgSendAddUpdateWecomDTO wecomDTO = JSONObject.parseObject(JSONObject.toJSONString(object), MsgSendAddUpdateWecomDTO.class);
            createAppChat(wecomDTO.getChatid(), wecomDTO.getName(), wecomDTO.getOwner(), wecomDTO.getAddUserList());
        }
        //修改群聊
        else if ("updateAppChat".equalsIgnoreCase(msgDTO.getTopic())) {
            MsgSendAddUpdateWecomDTO wecomDTO = JSONObject.parseObject(JSONObject.toJSONString(object), MsgSendAddUpdateWecomDTO.class);
            updateAppChat(wecomDTO.getChatid(), wecomDTO.getName(), wecomDTO.getOwner(), wecomDTO.getAddUserList(), wecomDTO.getDelUserList());
        }
        //默认发送消息
        else {
            MsgSendWecomDTO wecomDTO = JSONObject.parseObject(JSONObject.toJSONString(object), MsgSendWecomDTO.class);
            WecomMsgUtil.send(wecomDTO);
        }
    }


    private static class WecomMsgHolder {
        /**
         * 静态初始化器，由JVM来保证线程安全
         */
        private static final WecomMsgUtil INSTANCE = new WecomMsgUtil();
    }
}
